package com.xizi.single;


import java.lang.reflect.Constructor;

//双重检验锁机制是单例模式的最佳实现方式。内存占用率高，效率高，线程安全，多线程操作原子性。
public class Singleton4 {
    // 将自身实例化对象设置为一个属性，并用static修饰
    //如果不加volatile关键字，会出现空指针的问题
    private volatile static Singleton4 instance = null;

    // 构造方法私有化
    private Singleton4() {
    }

    // 静态方法返回该实例
    public static Singleton4 getInstance() {
        // 第一次检查instance是否被实例化出来，如果没有进入if块
        if (instance == null) {
            synchronized (Singleton4.class) {
                // 某个线程取得了类锁，实例化对象前第二次检查instance是否已经被实例化出来，如果没有，才最终实例出对象
                if (instance == null) {
                    instance = new Singleton4();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) throws Exception {
        //通过反射测试双重检验模式
        Singleton4 singleton4 = Singleton4.getInstance();
        Singleton4 singleton5 = Singleton4.getInstance();
        Constructor<Singleton4> constructor = Singleton4.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Singleton4 s2 = constructor.newInstance();
        System.out.println(singleton4 + "\n" + singleton5 + "\n" + s2);
        System.out.println("正常情况下，实例化两个实例是否相同：" + (singleton4 == singleton5));
        System.out.println("通过反射攻击单例模式情况下，实例化两个实例是否相同：" + (singleton4 == s2));

    }
}
